package com.nulldev.util.web.nTube.components.video_queue;

import java.util.concurrent.TimeUnit;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.concurrency.threadIt.v4.emapi.ExecutorManager;
import com.nulldev.util.concurrency.threadIt.v4.emapi.IExecutorManager;
import com.nulldev.util.concurrency.threadIt.v4.emapi.cntft.ControllableFutureTask;
import com.nulldev.util.concurrency.threadIt.v4.emapi.uft.Executable;
import com.nulldev.util.web.YouTubeExtractor.video.ExtractedVideo;

public class VideoQueueThread extends Thread implements Runnable {

	private final WaitableQueue<Executable<ExtractedVideo>> QUEUE;
	private final static IExecutorManager td = ExecutorManager.get();

	public VideoQueueThread() {
		this(VideoQueueMode.get());
	}

	public VideoQueueThread(final VideoQueueMode vqm) {
		super("nTube-VQ");
		switch (vqm) {
			case HIGH_THROUGHPUT:
				this.QUEUE = new TimedQueue<Executable<ExtractedVideo>>(100, 10, TimeUnit.MILLISECONDS);
				break;
			case MEDIUM_THROUGHPUT:
				this.QUEUE = new TimedQueue<Executable<ExtractedVideo>>(50, 50, TimeUnit.MILLISECONDS);
				break;
			case LOW_THROUGHPUT:
				this.QUEUE = new TimedQueue<Executable<ExtractedVideo>>(10, 100, TimeUnit.MILLISECONDS);
				break;
			case CUSTOM:
				this.QUEUE = VideoQueueMode.getCustom();
				break;
			case UNRESTRICTED_QUEUE:
			default:
				this.QUEUE = null;
				break;
		}
		super.start();
	}

	@Override
	public void run() {
		if (this.QUEUE == null)
			return;
		while (true) {
			try {
				final Executable<ExtractedVideo> ex = this.QUEUE.waitForItem();
				td.asyncSubmit(ex).waitFor(10, TimeUnit.SECONDS);
			} catch (Throwable ex) {
				JVM.errorln(ex);
			}
		}
	}

	public boolean submit(final Executable<ExtractedVideo> task) throws InterruptedException {
		/* Do not submit ControllableFutureTask, this is out-of-spec. */
		if (task instanceof ControllableFutureTask)
			return true;

		if (this.QUEUE == null) {
			td.asyncSubmit(task);
			return true;
		} else {
			return this.QUEUE.offer(task);
		}
	}
}
